// 可选 - ts 的样式校验 - 可通过这些直接查看源码
import type { ConfigEnv, ProxyOptions, UserConfig } from 'vite'

// 使用 defineConfig 获得类型提示；loadEnv 读取 .env.* 到对象中。
import { defineConfig, loadEnv } from 'vite'

// Vue 单文件组件支持：解析 .vue。
import vue from '@vitejs/plugin-vue'

// 可选1：在 Vue 中使用 JSX/TSX（如果不需要可移除）。
// import vueJsx from '@vitejs/plugin-vue-jsx'
// 可选2：为旧浏览器注入必要 polyfill，提高兼容性。
// import legacy from '@vitejs/plugin-legacy'
// 可选3：产出体积分析报告，定位大依赖。
// import { visualizer } from 'rollup-plugin-visualizer'
// 可选4：构建额外写出 .gz/.br 文件，服务端可按需返回。
// import viteCompression from 'vite-plugin-compression'

// 自动导入 Vue/Router/Pinia/Element Plus 等 API（vite 版）。
import AutoImport from 'unplugin-auto-import/vite'
// 组件按需自动注册（vite 版）。
import Components from 'unplugin-vue-components/vite'
// 让自动导入/注册识别 Element Plus 组件/API，并自动引入样式。
import { ElementPlusResolver } from 'unplugin-vue-components/resolvers'

// Node 路径模块，用于别名与路径拼接。
import path from 'path'

// 打包进度条
import progress from 'vite-plugin-progress'
import UnoCSS from 'unocss/vite'


// 简单的代理日志：打印方法、原始路径、目标地址+最终路径、响应码或错误
function attachProxyLogger(proxy: any, options: ProxyOptions) {
  const target = typeof options.target === 'string' ? options.target : ''
  proxy.on('proxyReq', (proxyReq: any, req: any) => {
    const method = (req?.method || 'GET').toUpperCase()
    const url = req?.url || ''
    const proxiedPath = proxyReq.path || url
    console.log(`[Proxy] ${method} ${url} -> ${target}${proxiedPath}`)
  })
  proxy.on('proxyRes', (proxyRes: any, req: any) => {
    const method = (req?.method || 'GET').toUpperCase()
    const url = req?.url || ''
    console.log(`[Proxy] [表情] ${method} ${url} <- ${proxyRes.statusCode}`)
  })
}

// 导出 Vite 配置，使用回调可拿到当前 mode（development/test/production）。
export default defineConfig(({ mode }: ConfigEnv): UserConfig => {
  // 读取当前模式下的 .env.* 文件的环境变量，第三个参数空串表示不过滤前缀（都读）。
  const env = loadEnv(mode, process.cwd(), '')

  // 会显示在终端而不是浏览器。
  console.log('node.js环境', mode, env.VITE_APP_TITLE);

  // 允许用 .env 自定义 MODE_NAME，否则回退到 Vite 的 mode。
  const MODE_NAME = env.MODE_NAME || mode
  // 生产环境标识：用于关闭 source map、移除 console 等。
  const isProd = MODE_NAME === 'production'
  // 测试环境标识：用于开启 source map，便于联调排错。
  const isTest = MODE_NAME === 'test'
  // 开发环境标识：用于开启 source map 与友好体验。
  const isDev = MODE_NAME === 'development'

  // 返回最终配置对象。
  return {
    // 在nginx的部署基础路径：让前端项目访问地址在端口后需加该路径
    base: isProd ? '/mySkyOut/' : '/',

    // 模块解析与路径别名。
    resolve: {
      // 将 @ 指向 src，统一导入路径风格。
      alias: { '@': path.resolve(__dirname, 'src') },
      // 这些扩展名在 import 导入时可省略，提升体验。
      extensions: ['.ts', '.tsx', '.js', '.jsx', '.mjs', '.json', '.vue'],
    },

    // 本地开发服务器设置（仅影响 `vite` 命令）。
    server: {
      // 开发端口：避免冲突。
      port: 3001,
      // 允许外部访问,控制台能显示本机局域网的前端项目运行地址
      host: '0.0.0.0',
      // 启动即自动打开浏览器。
      open: false,
      // HMR 热更新与错误覆盖层：便于第一时间看到报错。
      hmr: { overlay: true },
      // 代理后端接口：解决跨域，支持 WebSocket。
      proxy: {
        // 2.3-配置需要代理的路径
        // '/admin': {
        [env.VITE_APP_BASE_API_CANGQIONG]: {
          // 目标后端接口地址
          target: 'http://localhost:8080',
          // 修改 Origin 头以避开 CORS,允许跨域
          changeOrigin: true,
          // 允许代理 WS。
          ws: true,
          // 可选：重写路径（如果后端接口没有/admin前缀，删掉/admin传给后端）
          // rewrite: (path) => path.replace(/^\/admin/, ''),
          // 显示前端代理的日志 - 目标地址
          configure: (proxy, options) => attachProxyLogger(proxy, options),
        },

        '/downLoadFile': {
          target: 'http://localhost:8080', // 目标服务器地址
          changeOrigin: true, // 允许跨域
          // 允许代理 WS。
          ws: true,
          // 可选：重写路径（如果后端接口没有/api前缀）
          rewrite: (path) => path.replace(/^\/downLoadFile/, ''),
          // 显示前端代理的日志 - 目标地址 - 使用原始方法
          configure: (proxy) => {
            // @ts-ignore 由于 proxy 没有明确类型定义，我们需要忽略 TS 错误
            (proxy as any).on('proxyReq', (proxyReq, req, res) => {
              // 输出原请求地址（即浏览器请求的 URL）和代理后的目标地址
              console.log(`请求原地址: ${req.url}`)  // 打印原请求地址
              console.log(`代理后地址: ${proxyReq.protocol}//${proxyReq.host}${proxyReq.path}`)  // 打印代理后地址
            })
          }
        }
      },
      // 允许其他源访问 dev server（如调试 iframe）。
      cors: true,
    },

    // 预览构建产物的本地服务器 - 控制 vite preview 脚本的配置属性。npm run preview
    preview: {
      // 预览端口。
      port: 4173,
      // 是否自动打开浏览器。
      open: false,
    },

    // 构建产物与优化选项（`vite build`）。
    build: {
      // 目标语法版本：影响是否降级与 polyfill 需要。
      target: 'es2018',
      // 输出目录：最终可部署产物写入此处。
      outDir: 'dist',
      // 静态资源目录：相对 outDir 的子目录。
      assetsDir: 'assets',
      // 源码映射：dev/test 为 true 便于调试；prod 为 false 防止源码泄露（核心要求 #1）。
      sourcemap: isDev || isTest ? true : false,
      // 使用 esbuild 压缩，速度快；如需更细控制可换 'terser'。
      minify: 'esbuild',
      // 仅生产传递 esbuild 的 drop 选项：移除 console/debugger（核心要求 #2）。
      // @ts-expect-error Vite 运行时会合并 esbuild 选项。
      esbuild: isProd ? { drop: ['console', 'debugger'] } : undefined,
      // 小资源（4KB）转 base64 内联，减少请求数。
      assetsInlineLimit: 4096,
      // 透传高级 Rollup 配置：输出命名与分包策略。
      rollupOptions: {
        // 自定义输出规则。
        output: {
          // 动态 chunk 的文件命名：含 hash 利于长期缓存。
          chunkFileNames: 'assets/js/[name]-[hash].js',
          // 入口 chunk 的文件命名。
          entryFileNames: 'assets/js/[name]-[hash].js',
          // 静态资源命名：按类型分类到不同子目录。
          assetFileNames: ({ name }) => {
            // CSS 文件归类到 assets/css。
            if (/\.(css)$/.test(name ?? '')) return 'assets/css/[name]-[hash][extname]'
            // 图片统一归类到 assets/img。
            if (/\.(png|jpe?g|gif|svg|webp|avif)$/.test(name ?? '')) return 'assets/img/[name]-[hash][extname]'
            // 字体归类到 assets/fonts。
            if (/\.(woff2?|ttf|otf|eot)$/.test(name ?? '')) return 'assets/fonts/[name]-[hash][extname]'
            // 其他静态资源统一归类到 assets 根。
            return 'assets/[name]-[hash][extname]'
          },
          // 手动分包：把稳定依赖拆分，提升缓存命中率与首屏速度。
          manualChunks: {
            // Vue 生态单独打包：变更频率低、缓存价值高。
            vue: ['vue', 'vue-router', 'pinia'],
            // 通用第三方库打 vendor 包。
            vendor: ['axios', 'dayjs'],
          },
        },
      }
    },

    // 插件体系：Vue、自动导入、按需组件、兼容与分析等。
    plugins: [
      // 支持 .vue 单文件组件。
      vue(),

      // 支持 JSX/TSX（可移除）。
      // vueJsx(),

      // 打包进度条
      progress({
        format: 'building [:bar] :percent (:elapsed seconds)', // 文本模板
        width: 40,  // 进度条宽度
        total: 200, // 内部刻度（一般不用改）
        clear: true // 构建完成后清屏
      }),

      UnoCSS({ /* options */ }),

      // 自动导入函数/API：免去重复 import。
      AutoImport({
        // 自动导入 Vue/Router/Pinia 常用 API（ref/useRouter/useStore 等）。
        imports: ['vue', 'vue-router', 'pinia'],
        // 启用 Element Plus API 自动导入（如 ElMessage/ElMessageBox）。
        resolvers: [ElementPlusResolver()],
        // # 指定自动导入函数TS类型声明文件路径
        dts: path.resolve(path.resolve(__dirname, 'src'), "types", "auto-imports.d.ts"),
        // 生成 ESLint 全局声明，避免 no-undef。
        eslintrc: {
          // 是否自动生成 eslint 规则，建议生成之后设置 false 
          enabled: false,
          // 指定自动导入函数 eslint 规则的文件
          filepath: './.eslintrc-auto-import.json',
          globalsPropValue: true
        },
      }),

      // 组件按需自动注册：<el-*> 直接用。
      Components({
        // 解析 Element Plus 组件，并自动引入 Sass 样式（便于主题覆盖）。
        resolvers: [ElementPlusResolver({ importStyle: 'sass' })],
        // 生成 d.ts，<el-*> 有类型提示。
        dts: path.resolve(path.resolve(__dirname, 'src'), "types", "components.d.ts"),
      }),

      //   // 可选：旧浏览器兼容（按需开启）。
      //   legacy({ targets: ['defaults', 'not IE 11'], modernPolyfills: true }),
      //   // 仅生产：写出 .gz 压缩包，配合服务器按需返回。
      //   viteCompression({
      //     // 非生产禁用压缩插件，避免干扰开发。
      //     disable: !isProd,
      //     // 超过 10KB 才压缩：保证收益。
      //     threshold: 10 * 1024,
      //     // 压缩算法：gzip（也可换 'brotliCompress'）。
      //     algorithm: 'gzip',
      //     // 压缩文件扩展名。
      //     ext: '.gz',
      //   }),
      //   // 可选：打包体积可视化报告，定位大模块。
      //   visualizer({
      //     // 报告文件输出到根目录。
      //     filename: 'stats.html',
      //     // 使用树图展示大小占比。
      //     template: 'treemap',
      //     // 构建完不自动打开浏览器。
      //     open: false,
      //     // 在报告中显示 gzip 体积。
      //     gzipSize: true,
      //     // 在报告中显示 brotli 体积。
      //     brotliSize: true,
      //   }),
    ],

    // 仅这些前缀的 .env 变量会暴露到客户端，避免意外泄露敏感信息。
    envPrefix: ['VITE_', 'APP_'],


    // 编译期常量注入：在源码中可直接使用这些常量。
    // console.log('组件中使用', __BUILD_TIME__, __API_BASE__, import.meta.env.VITE_APP_TITLE)
    define: {
      // 注入应用版本（来自 package.json），便于 UI 显示或上报。
      __APP_VERSION__: JSON.stringify(process.env.npm_package_version),
      // 注入构建时间：便于排障或展示。
      __BUILD_TIME__: JSON.stringify(new Date().toISOString()),
      // 注入 API 基础地址：统一从常量读取，避免硬编码。
      __API_BASE__: JSON.stringify(env.VITE_API_BASE || '/'),
    },

    // CSS 相关高级设置：Modules、Sass 注入、PostCSS 等。
    css: {
      // 开发/测试开启 CSS source map；生产关闭，减少体积并防泄露。
      devSourcemap: isDev || isTest,
      // CSS Modules 行为定义（仅 *.module.* 生效）。
      modules: {
        // 默认使用局部作用域，避免样式污染。
        scopeBehaviour: 'local',
        // 生产使用短哈希；开发保留可读性更好的命名。
        generateScopedName: isProd ? '[hash:base64:8]' : '[name]__[local]__[hash:base64:5]',
      },
      // 预处理器选项：全局注入 Sass 变量并引入 sass:math。
      preprocessorOptions: {
        // 针对 scss 的全局注入。
        scss: {
          // 在每个 scss 文件前自动注入：可在 _variables.scss 覆盖 Element Plus 主题变量。
          // 在 @/styles目录下必须存在 globalColor.scss 文件 定义了scss常量
          // @use "sass:math"; - 会导致打包报错
          additionalData: `
            
            @use "@/styles/globalColor.scss" as *;
          `,
        },
      },
      // PostCSS 管道：这里启用 autoprefixer，也可另建 postcss.config.cjs。
      postcss: {
        // 自动补全兼容前缀。
        // plugins: [require('autoprefixer')()],
      },
    },

    // 依赖预构建：加速冷启动与热更新。
    optimizeDeps: {
      // 指定要预构建的依赖，避免首次启动慢。
      include: ['axios', 'dayjs'],
      // 限定扫描入口，减少无关扫描范围。
      entries: ['src/main.ts'],
    },
  }
})